home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Sprite 1984 - 1993
/
Sprite 1984 - 1993.iso
/
src
/
cmds
/
nfsmount
/
RCS
/
nfsLookup.c,v
< prev
next >
Wrap
Text File
|
1991-10-20
|
24KB
|
855 lines
head 1.5;
branch ;
access ;
symbols ;
locks ; strict;
comment @ * @;
1.5
date 91.10.20.12.38.28; author mottsmth; state Exp;
branches ;
next 1.4;
1.4
date 89.10.10.13.17.24; author douglis; state Exp;
branches ;
next 1.3;
1.3
date 89.09.12.14.32.44; author shirriff; state Exp;
branches ;
next 1.2;
1.2
date 88.11.14.15.15.06; author brent; state Exp;
branches ;
next 1.1;
1.1
date 88.11.02.12.44.18; author brent; state Exp;
branches ;
next ;
desc
@The main NFS lookup loop.
@
1.5
log
@Add remote mount points to support the mounting
of one NFS filesystem within another.
@
text
@/*
* nfsLookup.c --
*
* The main NFS pathname lookup procedure. NFS does lookup component
* at a time, while the Sprite interface is based on complete relative
* names. The NfsLookup procedure takes care of chopping the relative
* name into components and doing NFS calls to get the handle for
* each successive component.
*
* Copyright 1988 Regents of the University of California
* Permission to use, copy, modify, and distribute this
* software and its documentation for any purpose and without
* fee is hereby granted, provided that the above copyright
* notice appear in all copies. The University of California
* makes no representations about the suitability of this
* software for any purpose. It is provided "as is" without
* express or implied warranty.
*/
#ifndef lint
static char rcsid[] = "$Header: /sprite/src/cmds/nfsmount/RCS/nfsLookup.c,v 1.4 89/10/10 13:17:24 douglis Exp Locker: mottsmth $ SPRITE (Berkeley)";
#endif not lint
#include "stdio.h"
#include "nfs.h"
#include "sys/time.h"
#include "sys/stat.h"
#include "kernel/fs.h"
static int ExpandLink();
static void LookupCacheInsert();
static int CheckMountPoint();
NfsReadTest() { return; } ;
/*
* This array holds the names of mount points within our namespace
* so that we can force redirect lookups. The array is initialized
* from the command line options using the callback function
* NfsRecordMountPointProc.
*/
#define MAXMOUNTPOINTS 10
typedef struct RedirectNode {
char *local; /* Name (relative) in this filesystem */
char *remote; /* Name (absolute) where subtree is mounted */
} RedirectNode;
static RedirectNode redirectList[MAXMOUNTPOINTS];
static int redirectCount = 0;
/*
*----------------------------------------------------------------------
*
* NfsLookupTest --
*
* Stub on top of NfsLookup to call it and exercise it.
*
* Results:
* None.
*
* Side effects:
* Prints out the returned attributes of the file.
*
*----------------------------------------------------------------------
*/
void
NfsLookupTest(private, name)
ClientData private;
char *name;
{
NfsState *nfsPtr = (NfsState *)private;
diropokres dirResults;
diropargs dirArgs;
diropargs *dirArgsPtr = &dirArgs;
fattr *attrPtr = &dirResults.attributes;
int status;
char component[NFS_MAXNAMLEN];
Fs_RedirectInfo redirectInfo;
dirArgs.name = component;
status = NfsLookup(nfsPtr, NULL , name, FS_FOLLOW,
&dirResults, &dirArgsPtr, &redirectInfo);
if (status == EREMOTE) {
printf("REDIRECT => \"%s\"\n", redirectInfo.fileName);
} else if (status == 0) {
register int *intPtr;
printf("Handle of %s:%s/%s\n\t", nfsPtr->host, nfsPtr->nfsName, name);
NfsHandlePrint(&dirResults.file);
printf("\n");
printf("Parent handle\n\t");
NfsHandlePrint(&dirArgsPtr->dir);
printf("\n");
printf("Attributes of %s:%s/%s\n", nfsPtr->host, nfsPtr->nfsName, name);
printf("\tFileID %x FS_ID %x\n",
attrPtr->fileid,
attrPtr->fsid);
printf("\tType %d mode 0%o links %d size %d\n",
attrPtr->type,
attrPtr->mode,
attrPtr->nlink,
attrPtr->size);
} else {
if (dirArgsPtr != (diropargs *)NULL) {
printf("Parent of %s\n\t", dirArgsPtr->name);
NfsHandlePrint(&dirArgsPtr->dir);
printf("\n");
}
printf("Lookup of %s:%s/%s returns <%d>\n",
nfsPtr->host, nfsPtr->nfsName, name, status);
}
}
/*
*----------------------------------------------------------------------
*
* NfsLookup --
*
* Called to return a nfs_fh for a path inside NFS. Because NFS only
* does component-at-a-time lookup we have to loop through the
* pathname ourselves. This routine is modeled very closely on
* the Sprite kernel routine Fs_LocalLookup.
*
* Results:
* This returns an error code from NFS, or -1 if NFS access failed
* entirely. Upon NFS_OK return then *dirResultsPtr is filled in
* with the handle and attributes for the name looked up. If
* dirArgsPtrPtr is non-null then this indirectly references storage
* for the last pathname component and the handle of its parent.
* This information is filled in if possible, otherwise the pointer
* is cleared to indicate the information isn't available.
* EREMOTE is returned if a symbolic link to the root was
* encountered, or the pathname left via ".." out the top of the
* NFS system. *redirectInfoPtr gets filled in with the new
* pathname in this case.
*
* Side effects:
* None (yet).
*
*----------------------------------------------------------------------
*/
int
NfsLookup(nfsPtr, cwdFilePtr, name, useFlags, dirResultsPtr, dirArgsPtrPtr,
redirectInfoPtr)
NfsState *nfsPtr; /* Top level state for NFS connection */
NfsOpenFile *cwdFilePtr; /* Handle for directory at start of path.
* If NULL the mount point is used. */
char *name; /* Name relative to cwdHandle */
int useFlags; /* Sprite Lookup flags. FS_FOLLOW means
* follow symbolic links. */
diropokres *dirResultsPtr; /* Return - handle and attributes of name */
diropargs **dirArgsPtrPtr; /* If non-NULL **dirArgsPtrPtr is filled in
* with the last component of name and the
* handle for the parent directory. This is
* used when creating, removing, etc. Note
* that (*dirArgsPtrPtr)->name must point
* to storage for the pathname component. */
Fs_RedirectInfo *redirectInfoPtr; /* Returned name if a symbolic link to the
* root is encountered. Return value of
* the procedure is EREMOTE in this case. */
{
register char *curCharPtr;
register int compLen = -1;
register char *compPtr;
register nfs_fh *cwdHandlePtr;
register int status = (int) NFS_OK;
int numLinks = 0;
int haveGoodAttrs = 0;
diropargs *returnDirArgsPtr;
diropargs dirArgs;
diropres dirResults;
char component[NFS_MAXNAMLEN];
char expandedPath[NFS_MAXNAMLEN];
int isMountPoint;
/*
* Initialize lookup. Skip leading slashs, get a handle for the
* current starting point, fill in the diropargs that we'll be
* passing to the NFS server.
*/
redirectInfoPtr->prefixLength = 0; /* no remote links in NFS */
if (dirArgsPtrPtr != (diropargs **)NULL) {
returnDirArgsPtr = *dirArgsPtrPtr;
*dirArgsPtrPtr = (diropargs *)NULL; /* to indicate no parent, yet */
} else {
returnDirArgsPtr = (diropargs *)NULL;
}
curCharPtr = name;
while (*curCharPtr && *curCharPtr == '/') {
curCharPtr++;
}
if (cwdFilePtr == (NfsOpenFile *)NULL) {
cwdHandlePtr = nfsPtr->mountHandle;
} else {
cwdHandlePtr = cwdFilePtr->handlePtr;
}
dirArgs.name = component;
/*
* Loop through the pathname.
*/
while (*curCharPtr != '\0') {
/*
* Copy the next component and skip trailing slashes.
*/
compPtr = component;
while (*curCharPtr != '/' && *curCharPtr != '\0') {
*compPtr++ = *curCharPtr++;
}
compLen = compPtr - component;
if (compLen >= NFS_MAXNAMLEN) {
status = NFSERR_NAMETOOLONG;
goto exit;
}
*compPtr = '\0';
bcopy((char *)cwdHandlePtr, (char *)&dirArgs.dir, sizeof(nfs_fh));
isMountPoint = (bcmp((char *)cwdHandlePtr,
(char *)nfsPtr->mountHandle,
NFS_FHSIZE) == 0);
if ((isMountPoint) &&
(CheckMountPoint(component,redirectInfoPtr->fileName) >= 0)) {
(void)strcat(redirectInfoPtr->fileName, curCharPtr);
return(EREMOTE);
}
while (*curCharPtr == '/') {
curCharPtr++;
}
if (compLen == 2 && component[0] == '.' && component[1] == '.') {
/*
* Going to the parent directory, "..".
*/
if (isMountPoint) {
/*
* We are falling off the top of the NFS system. Copy the
* remaining part of the name, including the "../", into
* *newNamePtr and return that, instead of a handle.
*/
(void)strcpy(redirectInfoPtr->fileName, "../");
(void)strcat(redirectInfoPtr->fileName, curCharPtr);
return(EREMOTE);
}
} else if (compLen == 1 && component[0] == '.') {
/*
* Already have a handle on ".", the current directory.
*/
continue;
}
/*
* Lookup the next component via NFS. Remember that the current
* handle has been copied into dirArgs, and the result handle
* will be copied into dirResults by the XDR routines.
*/
if (clnt_call(nfsPtr->nfsClnt, NFSPROC_LOOKUP, xdr_diropargs, &dirArgs,
xdr_diropres, &dirResults, nfsTimeout) != RPC_SUCCESS) {
clnt_perror(nfsPtr->nfsClnt, "NfsLookup: RPC nfsproc_lookup_2");
status = -1;
goto exit;
} else if (dirResults.status != NFS_OK) {
/*
* Lookup failed. If we failed on the last component we set up
* the returned dirArgs so they are useful for a subsequent
* create. returnDirArgsPtr is the original pointer to
* good storage provided by our caller. We set the pointer
* to this pointer to indicate the storage now has valid data.
*/
status = (int)dirResults.status;
if (*curCharPtr == '\0' && returnDirArgsPtr != (diropargs *)NULL) {
bcopy((char *)&dirArgs.dir, (char *)&returnDirArgsPtr->dir,
sizeof(nfs_fh));
strcpy(returnDirArgsPtr->name, component);
*dirArgsPtrPtr = returnDirArgsPtr;
}
goto exit;
} else {
/*
* Lookup succeeded. The lookup result is cached for
* a brief period to optimize heavy traffic through top-level
* directories.
*/
haveGoodAttrs = 1;
cwdHandlePtr = &dirArgs.dir;
LookupCacheInsert(cwdHandlePtr, component, &dirResults);
if ((*curCharPtr != '\0' || (useFlags & FS_FOLLOW)) &&
dirResults.diropres_u.diropres.attributes.type == NFLNK) {
/*
* Hit a symbolic link in the middle of a pathname or at
* the end are we are told to follow it.
*/
numLinks++;
if (numLinks > FS_MAX_LINKS) {
status = ELOOP;
goto exit;
} else {
int offset; /* Distance of existing name from the
* start of its buffer */
if (numLinks == 1) {
offset = (int)curCharPtr - (int)name;
} else {
offset = (int)curCharPtr -
(int)(expandedPath);
}
status = ExpandLink(nfsPtr, &dirResults, curCharPtr, offset,
expandedPath);
if (status != NFS_OK) {
goto exit;
}
curCharPtr = expandedPath;
}
if (*curCharPtr == '/') {
/*
* A link back to the root has to be handled by the
* prefix table in the Sprite kernel.
*/
strcpy(redirectInfoPtr->fileName, expandedPath);
return(EREMOTE);
}
/*
* The link was relative so we reset the current handle
* to point to the same place we found the link.
*/
cwdHandlePtr = &dirArgs.dir;
} else {
/*
* Not a symbolic link.
* Advance the current handle to the component we just found.
*/
cwdHandlePtr = &dirResults.diropres_u.diropres.file;
}
}
}
/*
* Lookup complete. Copy out our results.
*/
if (haveGoodAttrs) {
bcopy((char *)&dirResults.diropres_u.diropres, (char *)dirResultsPtr,
sizeof(diropokres));
if (returnDirArgsPtr != (diropargs *)NULL) {
/*
* Our caller wants information about the parent directory
* for a delete, rename, or link. We restore the pointer
* to indicate that this information has been provided.
*/
bcopy((char *)&dirArgs.dir, (char *)&returnDirArgsPtr->dir,
sizeof(nfs_fh));
strcpy(returnDirArgsPtr->name, component);
*dirArgsPtrPtr = returnDirArgsPtr;
}
} else {
/*
* We didn't go throught the lookup loop because our caller asked
* for an empty name. We do an explicit get attributes.
*/
register attrstat *tmpAttrPtr;
tmpAttrPtr = nfsproc_getattr_2(cwdHandlePtr, nfsPtr->nfsClnt);
if (tmpAttrPtr == (attrstat *)NULL) {
clnt_perror(nfsPtr->nfsClnt, "NfsLookup: RPC nfsproc_getattr_2");
status = -1;
goto exit;
} else if (tmpAttrPtr->status != NFS_OK) {
status = (int)tmpAttrPtr->status;
goto exit;
} else {
bcopy((char *)cwdHandlePtr, (char *)&dirResultsPtr->file,
NFS_FHSIZE);
bcopy((char *)&tmpAttrPtr->attrstat_u.attributes,
(char *)&dirResultsPtr->attributes, sizeof(fattr));
}
}
exit:
if (status == -1 && errno != 0) {
status = errno;
}
return(status);
}
/*
*----------------------------------------------------------------------
*
* LookupCacheInsert --
*
* Tuck away a <nfs_fh, component> => <nfs_fh> mapping.
*
* Results:
* None.
*
* Side effects:
* Adds an entry into the component cache.
*
*----------------------------------------------------------------------
*/
static void
LookupCacheInsert(component, dirResultsPtr)
char *component; /* Pathname component just looked up. */
diropres *dirResultsPtr; /* Return info from NFS server */
{
return;
}
/*
*----------------------------------------------------------------------
*
* ExpandLink --
* Expand a link by shifting the remaining pathname over and
* inserting the contents of the link file.
*
* Results:
* None.
*
* Side effects:
* Expands the link into nameBuffer.
*
*----------------------------------------------------------------------
*/
static int
ExpandLink(nfsPtr, dirResultsPtr, curCharPtr, offset, nameBuffer)
NfsState *nfsPtr; /* Needed for ReadLink RPC */
diropres *dirResultsPtr; /* Handle + attrs of the link file */
char *curCharPtr; /* Points to beginning of the remaining
* name that has to be shifted */
int offset; /* Offset of curCharPtr within its
* buffer */
char nameBuffer[]; /* New buffer for the expanded name */
{
ReturnStatus status;
int linkNameLength; /* The length of the name in the
* link NOT including the Null */
readlinkres readLinkResult;
char savedC;
register char *srcPtr;
register char *dstPtr;
linkNameLength = dirResultsPtr->diropres_u.diropres.attributes.size;
if (*curCharPtr == '\0') {
/*
* There is no pathname to shift around.
* Make sure the new name is null terminated
*/
nameBuffer[linkNameLength] = '\0';
} else {
/*
* Set up srcPtr to point to the start of the remaining pathname.
* Set up dstPtr to point to just after where the link will be,
* ie. just where the '/' is that separates the link value from
* the remaining pathname.
*/
srcPtr = curCharPtr;
dstPtr = &nameBuffer[linkNameLength];
if (linkNameLength < offset) {
/*
* The remaining name has to be shifted left.
* For example, /first is a link to /usr (or /users). With the
* filename /first/abc, curCharPtr will point to the 'a' in "abc".
* dstPtr points to the '\0' after "/usr".
*
* / f i r s t / a b c \0 { current name, offset = 7 }
* / u s r \0 { link name, len = 4 }
* / u s e r s \0 { or len = 6 }
* / u s r / a b c { final result }
*
* Insert the separating '/' first, then start at the beginning
* of the remaining name and copy it into the new buffer.
*/
*dstPtr = '/';
dstPtr++;
for( ; ; ) {
*dstPtr = *srcPtr;
if (*srcPtr == '\0') {
break;
}
dstPtr++;
srcPtr++;
}
} else {
/*
* The remaining name has to be shifted right.
* For example, /first is a link to /usr/tmp. With the filename
* /first/abc, curCharPtr will point to the 'a' in "abc".
* dstPtr points to the '\0' after "/usr/tmp".
*
* / f i r s t / a b c \0 { current name, offset = 7 }
* / u s r / t m p \0 { link name, len = 8 }
* / u s r / t m p / a b c { final result }
*
* Zoom to the end of the name (adjusting dstPtr to account
* for where the '/' will go) and then shift the name right.
*/
dstPtr++;
while (*srcPtr != '\0') {
srcPtr++;
dstPtr++;
}
while (srcPtr >= curCharPtr) {
*dstPtr = *srcPtr;
dstPtr--;
srcPtr--;
}
*dstPtr = '/';
}
}
/*
* Read and insert the link name in front of the remaining name
* that was just shifted over. By initializing the character string
* pointer (data) before the RPC the XDR routines know to use
* the existing buffer and not allocate a new one. Also, the XDR routines
* are going to null terminate the string and stomp on the character
* after the link value, so we save and restore that.
*/
readLinkResult.readlinkres_u.data = nameBuffer;
savedC = nameBuffer[linkNameLength];
if (clnt_call(nfsPtr->nfsClnt, NFSPROC_READLINK, xdr_nfs_fh,
&dirResultsPtr->diropres_u.diropres.file, xdr_readlinkres,
&readLinkResult, nfsTimeout) != RPC_SUCCESS) {
clnt_perror(nfsPtr->nfsClnt, "nfsproc_lookup_2");
if (errno != 0) {
return(errno);
} else {
return(-1);
}
}
nameBuffer[linkNameLength] = savedC;
return(readLinkResult.status);
}
/*
*----------------------------------------------------------------------
*
* NfsWriteTest --
*
* Test harness for NFS writing. This opens a NFS file and copies
* a Sprite file to an NFS file.
*
* Results:
* None.
*
* Side effects:
* Prints out the returned attributes of the file.
*
*----------------------------------------------------------------------
*/
void
NfsWriteTest(private, spriteName, nfsName)
ClientData private;
char *spriteName;
char *nfsName;
{
NfsState *nfsPtr = (NfsState *)private;
diropres longDirResults;
diropokres *dirResultsPtr = &longDirResults.diropres_u.diropres;
int status;
char *newName;
createargs createArgs;
diropargs *wherePtr = &createArgs.where;
sattr *sattrPtr = &createArgs.attributes;
char component[NFS_MAXNAMLEN];
Fs_RedirectInfo redirectInfo;
wherePtr->name = component;
status = NfsLookup(nfsPtr, NULL /* fix */, nfsName,
FS_FOLLOW, dirResultsPtr, &wherePtr, &redirectInfo);
if (status == EREMOTE) {
printf("REDIRECT => \"%s\"\n", redirectInfo.fileName);
} else if (status == NFSERR_NOENT && wherePtr != (diropargs *)NULL) {
sattrPtr->mode = 0644;
sattrPtr->uid = 1020; /* non-existent! */
sattrPtr->gid = 94; /* non-existent! */
sattrPtr->size = 0;
sattrPtr->atime.seconds = -1;
sattrPtr->atime.useconds = -1;
sattrPtr->mtime.seconds = -1;
sattrPtr->mtime.useconds = -1;
if (clnt_call(nfsPtr->nfsClnt, NFSPROC_CREATE, xdr_createargs,
&createArgs, xdr_diropres, &longDirResults, nfsTimeout)
!= RPC_SUCCESS) {
clnt_perror(nfsPtr->nfsClnt, "NFSPROC_CREATE");
return;
}
status = longDirResults.status;
printf("Create of %s:%s/%s returns <%d>\n",
nfsPtr->host, nfsPtr->nfsName, nfsName, status);
} else {
printf("Lookup of %s:%s/%s returns <%d>\n",
nfsPtr->host, nfsPtr->nfsName, nfsName, status);
}
}
/*
*----------------------------------------------------------------------
*
* NfsRecordMountPointProc --
*
* Add a sub-mount point to our list.
*
* This routine is called by the Opt_Parse routine when it sees
* a -m option.
*
* Results:
* None.
*
* Side effects:
* None.
*
* Note:
* NFS allows one file system to be mounted within another NFS
* namespace. This causes problems for Sprite since it expects
* to have a remote link at each mount point. The kluge of a
* solution is to tell nfsmount where the sub-mount points are
* in its namespace so that it can return EREMOTE when a lookup
* enters one of these subdomains.
*
*----------------------------------------------------------------------
*/
int
NfsRecordMountPointProc(option, argc, argv)
char *option; /* should point to 'm' */
int argc; /* number of remaining args */
char **argv; /* arg pointers */
{
int i;
struct stat statBuf;
if ((argc < 2) ||
(*argv[0] == '-') ||
(*argv[0] == '/') ||
(*argv[1] != '/')) {
fprintf(stderr, "Usage -m option: relative-local-name absolute-remote-name\n");
exit(-1);
}
if (redirectCount >= MAXMOUNTPOINTS) {
fprintf(stderr, "Too many mount points specified. (%d max)\n",
MAXMOUNTPOINTS);
exit(-1);
}
if (lstat(argv[1], &statBuf) < 0) {
perror(argv[1]);
exit(-1);
}
if ((statBuf.st_mode & S_IFMT) != S_IFRLNK) {
fprintf(stderr,"Not a remote link: %s\n", argv[1]);
exit(-1);
}
redirectList[redirectCount].local = argv[0];
redirectList[redirectCount].remote = argv[1];
redirectCount++;
for (i=0,argc-=2; i<argc; i++) {
argv[i] = argv[i+2];
}
/* tell Opt_Parse that we consumed 2 arguments */
return argc;
}
/*
*----------------------------------------------------------------------
*
* CheckMountPoint --
*
* Check a name against the mount point list.
*
* Results:
* None.
*
* Side effects:
* Uses but does not modify the global redirectList.
*
*----------------------------------------------------------------------
*/
static int
CheckMountPoint(name, redirectPtr)
char *name; /* name of local file to verify */
char *redirectPtr; /* name to redirect to */
{
int i;
for (i=0; i<redirectCount; i++) {
if (strcmp(redirectList[i].local,name) == 0) {
strcpy(redirectPtr, redirectList[i].remote);
return i;
}
}
return -1;
}
@
1.4
log
@Changed void * to VoidPtr to remove lint
@
text
@d20 1
a20 1
static char rcsid[] = "$Header: /a/newcmds/nfsmount/RCS/nfsLookup.c,v 1.3 89/09/12 14:32:44 shirriff Exp Locker: douglis $ SPRITE (Berkeley)";
d27 1
d33 1
d36 17
d177 3
d213 2
a214 1
if (compPtr - component >= NFS_MAXNAMLEN) {
d219 12
a230 1
compLen = compPtr - component;
a233 2
bcopy((char *)cwdHandlePtr, (char *)&dirArgs.dir, sizeof(nfs_fh));
d238 1
a238 2
if (bcmp((char *)cwdHandlePtr, (char *)nfsPtr->mountHandle,
NFS_FHSIZE) == 0) {
d307 1
a307 1
(int)(redirectInfoPtr->fileName);
d310 1
a310 1
redirectInfoPtr->fileName);
d314 1
a314 1
curCharPtr = redirectInfoPtr->fileName;
d321 1
d594 107
@
1.3
log
@Updated to new Fs_ typedefs
@
text
@d20 1
a20 1
static char rcsid[] = "$Header: /a/newcmds/nfsmount/RCS/nfsLookup.c,v 1.2 88/11/14 15:15:06 brent Exp Locker: shirriff $ SPRITE (Berkeley)";
d151 1
a151 1
register int status = NFS_OK;
d230 1
a230 1
clnt_perror(nfsPtr->nfsClnt, "nfsproc_lookup_2");
d331 3
a333 1
clnt_perror(nfsPtr->nfsClnt, "nfsproc_getattr_2");
d345 3
d489 5
a493 1
return(-1);
@
1.2
log
@Added user authentication
@
text
@d20 1
a20 1
static char rcsid[] = "$Header: /sprite/users/brent/nfstest/RCS/nfsLookup.c,v 1.1 88/11/02 12:44:18 brent Exp $ SPRITE (Berkeley)";
d62 1
a62 1
FsRedirectInfo redirectInfo;
d107 1
a107 1
* the Sprite kernel routine FsLocalLookup.
d143 1
a143 1
FsRedirectInfo *redirectInfoPtr; /* Returned name if a symbolic link to the
d521 1
a521 1
FsRedirectInfo redirectInfo;
@
1.1
log
@Initial revision
@
text
@d20 1
a20 1
static char rcsid[] = "$Header: fsPfs.c,v 6.0 88/10/11 15:52:49 brent Exp $ SPRITE (Berkeley)";
d128 1
a128 1
NfsLookup(nfsPtr, cwdHandlePtr, name, useFlags, dirResultsPtr, dirArgsPtrPtr,
d131 1
a131 1
nfs_fh *cwdHandlePtr; /* Handle for directory at start of path.
d150 1
d174 1
a174 1
if (cwdHandlePtr == (nfs_fh *)NULL) {
d176 2
@